/*****************************************************************
Wowengine - v0.1

File: wen_geometry.cpp
Creation date: 2012-10-15
*****************************************************************/
#include "wen_geometry.h"
#include <iostream>

using namespace wen;

Geometry::Geometry()
:
Spatial(),
m_usRed(0),
m_usGreen(0),
m_usBlue(0),
m_iVertexCount(0),
m_iIndexCount(0),
m_iPrimitiveCount(0),
m_pkVertexPool(NULL),
m_psIndexPool(NULL)
{
	m_pkModelBV = new BVH();
	m_pkTransformedBV = new BVH();
}

Geometry::~Geometry()
{
	delete m_pkModelBV;
	m_pkModelBV = NULL;
}

VertexBuffer<TextureVertex, TEXTURE_VERTEX>::Ptr Geometry::GetVB()
{
	return m_kVertexTextureBuffer;
}
//----------------------------------------------------------------
const VertexBuffer<TextureVertex, TEXTURE_VERTEX>::Ptr Geometry::GetVB() const
{
	return m_kVertexTextureBuffer;
}

void Geometry::SetVB(VertexBuffer<TextureVertex, TEXTURE_VERTEX>::Ptr kTextureBuffer)
{
	m_kVertexTextureBuffer = kTextureBuffer;
}

void Geometry::SetColor(unsigned short usRed, unsigned short usGreen, unsigned short usBlue)
{
	m_usRed = usRed;
	m_usGreen = usGreen;
	m_usBlue = usBlue;

	/*TextureVertex* pkV = &(m_akVertices[0]);
	pkV->ulColor = D3DCOLOR_XRGB(m_usRed, m_usGreen, m_usBlue);
	pkV = &(m_akVertices[1]);
	pkV->ulColor = D3DCOLOR_XRGB(m_usRed, m_usGreen, m_usBlue);
	pkV = &(m_akVertices[2]);
	pkV->ulColor = D3DCOLOR_XRGB(m_usRed, m_usGreen, m_usBlue);
	pkV = &(m_akVertices[3]);
	pkV->ulColor = D3DCOLOR_XRGB(m_usRed, m_usGreen, m_usBlue);
	pkV = &(m_akVertices[4]);
	pkV->ulColor = D3DCOLOR_XRGB(m_usRed, m_usGreen, m_usBlue);
	pkV = &(m_akVertices[5]);
	pkV->ulColor = D3DCOLOR_XRGB(m_usRed, m_usGreen, m_usBlue);
	pkV = &(m_akVertices[6]);
	pkV->ulColor = D3DCOLOR_XRGB(m_usRed, m_usGreen, m_usBlue);
	pkV = &(m_akVertices[7]);
	pkV->ulColor = D3DCOLOR_XRGB(m_usRed, m_usGreen, m_usBlue);*/
}

void Geometry::Update(float fTimeBetweenFrames)
{
	Spatial::Update(fTimeBetweenFrames);
}

void Geometry::Draw(Render& rkRender)
{
	Spatial::Draw(rkRender);

	//m_bVisible = CheckBVHFrustumCollision(m_pkModelBV, rkRender);
	//m_bVisible = CheckBVHFrustumCollision(m_pkTransformedBV, rkRender);

	if(m_bVisible)
	{		
		std::string nodeName = m_pkParent->GetName();
		std::cout << nodeName << "\n";	

		//Set actual Material
		if (m_pkMaterial)
		{		
			rkRender.BindMaterial(m_pkMaterial->GetMaterial());					
		}		

		//Spatial::Draw(rkRender);

		rkRender.UnbindTexture(); //Unbind last Texture

		if(m_pkTexture)
		{
			if(!rkRender.BindTexture(*m_pkTexture))
			{
				printf("Error Binding Texture\n");
			}
		}

		if(m_kVertexTextureBuffer)
		{
			if(!rkRender.BindVB(m_kVertexTextureBuffer))
			{
				printf("Error Binding Vertex Buffer\n");
			}
		}

		if(m_kIndexBuffer)
		{
			if(!rkRender.BindIB(m_kIndexBuffer))
			{
				printf("Error Binding Index Buffer\n");
			}
		}

		rkRender.Draw(m_psIndexPool);
	}

	//UpdateBoundingVolume(rkRender);
}

void Geometry::CalculateNormals()
{
	// calcular face normals
}

void Geometry::NormalizeNormal(TextureVertex &pkTextureVertex)
{
	float fModule = sqrt((pkTextureVertex.fNX * pkTextureVertex.fNX) +
						 (pkTextureVertex.fNY * pkTextureVertex.fNY) +
						 (pkTextureVertex.fNZ * pkTextureVertex.fNZ));

	pkTextureVertex.fNX /= fModule;
	pkTextureVertex.fNY /= fModule;
	pkTextureVertex.fNZ /= fModule;
}

void Geometry::SetCurrentMaterial(Material* theMaterial)
{
	m_pkMaterial = theMaterial;

	if (m_pkMaterial->GetTextureName().compare("") != 0)
	{
		m_pkTexture = Texture::Ptr(new Texture(m_pkMaterial->GetTextureName(), D3DCOLOR_XRGB(255, 255, 255)));
	}
}

void Geometry::AddMaterial(Material* theMaterial)
{
	std::vector<Material*>::iterator iter = m_pkMaterialVector.begin();
	bool canAdd = true;

	for(; iter != m_pkMaterialVector.end(); iter++)
	{
		if ((*iter) == theMaterial)
		{
			canAdd = false;
			break;
		}
		if(canAdd)
		{
			m_pkMaterialVector.push_back(theMaterial);
		}		
	}
}

void Geometry::UpdateBoundingVolume(Render& rkRender)
{
	m_pkModelBV->TransformBVHVertex(&m_worldTransform);

	if (m_pkParent)
		m_pkParent->UpdateBoundingVolume(rkRender);
}